﻿using System;
using System.Web.UI;
using System.Reflection;

namespace Carbon.Web.Forms.jQueryForms
{
    public class ValidatorControl : Control, IValidator
    {
        #region Classes (1)
        private class DefaultValidatorControlTemplate : Control, ITemplate
        {
            #region Fields (1)
            private ValidatorControl m_Validator = default(ValidatorControl);
            #endregion

            #region Properties (1)
            public ValidatorControl Validator
            {
                get
                {
                    return m_Validator;
                }
            }
            #endregion

            #region Constructors (1)
            public DefaultValidatorControlTemplate(ValidatorControl validator)
                : base()
            {
                if (validator == null) throw new ArgumentNullException("validator");

                this.m_Validator = validator;
            }
            #endregion

            #region Methods (2)

            public void InstantiateIn(Control container)
            {
                container.Controls.Add(this);
            }

            public override void RenderControl(HtmlTextWriter writer)
            {
                if (Validator.ValidationException != null)
                {
                    writer.Write(@"<div class=""carbon-error"">");
                    writer.WriteEncodedText(Validator.ValidationException.Message);
                    writer.Write("</div>");
                }
            }

            #endregion
        }
        #endregion

        #region Fields (4)
        private ApplicationException m_ValidationException = default(ApplicationException);

        private bool m_IsValid = true;

        private String m_ValidationFailedClass = default(String);

        private ITemplate m_RenderTemplate = default(ITemplate);
        #endregion

        #region Events (1)
        public event EventHandler<ValidatorEventArgs> ValidateRules;
        #endregion

        #region Properties (4)
        public bool IsValid
        {
            get
            {
                return m_IsValid;
            }
            set
            {
                m_IsValid = value;
            }
        }
        [TemplateContainer(typeof(ValidatorControl))]
        public ITemplate RenderTemplate
        {
            get
            {
                if (m_RenderTemplate == null) throw new NullReferenceException("m_RenderTemplate");
                return m_RenderTemplate;
            }
            set
            {
                if (value == null) throw new NullReferenceException("value");
                m_RenderTemplate = value;
            }
        }
        public ApplicationException ValidationException
        {
            get
            {
                return m_ValidationException;
            }
            set
            {
                m_ValidationException = value;
            }
        }
        public String ValidationFailedClass
        {
            get
            {
                return m_ValidationFailedClass;
            }
            set
            {
                m_ValidationFailedClass = value;
            }
        }
        #endregion

        #region Constructors (1)
        public ValidatorControl()
        {
            m_RenderTemplate = new DefaultValidatorControlTemplate(this);
        }
        #endregion

        #region Methods (3)

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            if (ValidateRules == null) throw new NullReferenceException("Please specify Validation event handler (OnValidateRules = \"...\").");
        }

        public static void RenderValidationError(HtmlTextWriter writer, Exception ex)
        {
            while (ex is TargetInvocationException)
            {
                ex = ((TargetInvocationException)ex).InnerException;
            }

            String error = ex.Message;

            if (error == null)
                error = Errors.InvalidValue;

            writer.Write("<div class=\"carbon-error\">");
            writer.WriteEncodedText(error); writer.Write("</p></div>");
        }

        protected override void Render(HtmlTextWriter writer)
        {
            if (!IsValid)
            {
                RenderValidationError(writer, ValidationException);
            }
        }

        public virtual void OnValidateRules(ValidatorEventArgs args)
        {
            if (ValidateRules != null)
            {
                ValidateRules(this, args);
            }
        }

        public void Validate()
        {
            ValidatorEventArgs args = new ValidatorEventArgs();

            try
            {
                OnValidateRules(args);
                IsValid = true;
            }
            catch (ApplicationException ex)
            {
                ValidationException = ex;
                IsValid = false;
            }
        }

        #endregion
    }
}
